﻿using Niknak.Services.ServiceCore;
using Niknak.Services.TaskScheduler.Interfaces;
using Niknak.Services.TaskScheduler.Wcf;
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.ServiceModel;

namespace Niknak.Services.TaskScheduler
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class WcfEndpoint<ExceptionHandlerType, ScheduledTaskType, AuditLogType, AuditLogEntryType> : IWcfEndpoint
        where ExceptionHandlerType : IExceptionHandler, new()
        where ScheduledTaskType : Interfaces.DataModel.IScheduledTask, new()
        where AuditLogType : Interfaces.DataModel.IAuditLog<AuditLogEntryType>, new()
        where AuditLogEntryType : Interfaces.DataModel.IAuditLogEntry
    {
        public delegate bool ResetDelegate();
        public ResetDelegate DoReset;

        public delegate bool RestartDelegate();
        public RestartDelegate DoRestart;

        public delegate bool RaiseIterationCompletedEventDelegate(Guid scheduledTaskId, DateTime iterationDate);
        public RaiseIterationCompletedEventDelegate DoRaiseIterationCompletedEvent;

        #region IWcfEndpoint Members

        public string Ping()
        {
            return "PONG";
        }

        public Guid[] GetRunningTaskIds()
        {
            List<Guid> taskIds = new List<Guid>();
            taskIds.AddRange(AdvancedTask<ExceptionHandlerType, ScheduledTaskType, AuditLogType, AuditLogEntryType>.TaskIDsInProgress);
            taskIds.AddRange(SimpleTask<ExceptionHandlerType, ScheduledTaskType, AuditLogType, AuditLogEntryType>.TaskIDsInProgress);
            return taskIds.ToArray();
        }

        public bool Reset()
        {
            if (DoReset == null)
                return false;

            return DoReset();
        }

        public bool Restart()
        {
            if (DoRestart == null)
                return false;

            return DoRestart();
        }

        public bool RaiseIterationCompletedEvent(Guid scheduledTaskId, DateTime iterationDate)
        {
            if (DoRaiseIterationCompletedEvent == null)
                return false;

            return DoRaiseIterationCompletedEvent(scheduledTaskId, iterationDate);
        }

        public long GetServiceUptime()
        {
            DateTime startTime = Engine<ExceptionHandlerType, ScheduledTaskType, AuditLogType, AuditLogEntryType>.ServiceStartTime;
            if (startTime == DateTime.MaxValue)
                return 0;
            return (long)(DateTime.UtcNow - startTime).TotalSeconds;
        }

        public long GetEndpointUptime()
        {
            DateTime startTime = Engine<ExceptionHandlerType, ScheduledTaskType, AuditLogType, AuditLogEntryType>.EndpointStartTime;
            if (startTime == DateTime.MaxValue)
                return 0;
            return (long)(DateTime.UtcNow - startTime).TotalSeconds;
        }

        public string GetCustomEventLogName()
        {
            return new ExceptionHandlerType().CustomEventLogName;
        }

        public SerializableEventRecord[] ReadFromEventLog(string logName, InternalEnums.EventLogLevel[] logLevels, string providerName, DateTime afterTimestamp, DateTime beforeTimestamp, int skip, int take)
        {
            return new ExceptionHandlerType().ReadFromEventLog(logName, logLevels.Select(l => (int)l).ToArray(), providerName, afterTimestamp, beforeTimestamp, skip, take)
                .Select(e => new SerializableEventRecord(e))
                .ToArray();
        }

        #endregion
    }
}
